﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AudiPyme.DAL;

namespace AudiPyme.BLL
{
    public class ActivosInformeNegocio
    {
        //Método que recoge los datos de los Activos de un Informe y los formatea para incorporarlos al Informe de A/R
        public static List<ActivosDatosInforme> RecogeActivosInforme(int IdInforme)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            List<ActivosDatosInforme> ActivosEmpresa = new List<ActivosDatosInforme>();
            ActivosEmpresa = (from ActInf in agenteBD.ActivosInformeEstablecer
                              join ActEmp in agenteBD.ActivosEmpresaEstablecer on ActInf.IdActivo equals ActEmp.IdActivo
                              join TipAct in agenteBD.TiposActivosEstablecer on ActEmp.IdTipoActivo equals TipAct.IdTipoActivo
                              where ActInf.IdInforme == IdInforme
                              orderby ActInf.ValorEstrategicoInforme descending, ActInf.CosteActivoInforme descending
                              select new ActivosDatosInforme { Id = ActInf.IdActivo, Nombre = ActEmp.Nombre, TipoActivo = TipAct.TipoActivo, Coste = ActInf.CosteActivoInforme, ValorEstrategico = "Nulo" }).ToList();
            foreach (ActivosDatosInforme Act in ActivosEmpresa)
            {
                int IdValorActivo = (from ActInf in agenteBD.ActivosInformeEstablecer
                                     where ActInf.IdInforme == IdInforme && ActInf.IdActivo == Act.Id
                                     select ActInf.ValorEstrategicoInforme).Single();
                Act.ValorEstrategico = DeserializaValorEstrategico(IdValorActivo);
            }

            return ActivosEmpresa;
        }

        //Método que deserializa los valores almacenados del atributo valor estratégico
        public static String DeserializaValorEstrategico(int ValorEstrategico)
        {
            switch (ValorEstrategico)
            {
                case 1:
                    return "Bajo";
                case 2:
                    return "Medio";
                case 3:
                    return "Alto";
                default:
                    return "Nulo";
            }
        }

        //Recoge datos formateados para un diagrama de barras con los Activos que hay en un informe
        public static List<PuntoIntXY> ActivosTipoActivoInformeXY(int IdInforme)
        {
            List<PuntoIntXY> LActivosTipoXY = new List<PuntoIntXY>();
            List<String> TiposActivos = TiposActivosFactory.ListaTiposActivos();
            List<int> LNumActTipActEmp = TiposActivosFactory.NumActivosTipActivoInforme(IdInforme);
            for (int i = 0; i < TiposActivos.Count(); i++)
            {
                //Si tenemos valores del tipo de activo lo mostramos en la gráfica. Si no, no
                if (LNumActTipActEmp[i] != 0)
                {
                    PuntoIntXY NuevoPunto = new PuntoIntXY();
                    NuevoPunto.X = TiposActivos[i];
                    NuevoPunto.Y = LNumActTipActEmp[i];
                    LActivosTipoXY.Add(NuevoPunto);
                }
            }
            return LActivosTipoXY;
        }

        //Método que recoge los activos de un informe y los formatea para mostrarlos en un diagrama de barras según su valor estratégico
        public static List<PuntoIntXY> ActivosValorEstrategicoInformeXY(int IdInforme)
        {
            List<PuntoIntXY> LActivosValorXY = new List<PuntoIntXY>();
            List<int> ActivosPorValor = ActivosInformeFactory.ActivosInformePorValor(IdInforme);
            List<String> TipoValores = ActivosEmpresaFactory.TiposValorEstrategico();
            for (int i = 0; i < TipoValores.Count(); i++)
            {
                PuntoIntXY NuevoPunto = new PuntoIntXY();
                NuevoPunto.X = TipoValores[i];
                NuevoPunto.Y = ActivosPorValor[i];
                NuevoPunto.Serie = TipoValores[i];
                LActivosValorXY.Add(NuevoPunto);
            }
            return LActivosValorXY;
        }

        //Formatea los activos de un informe para agrupados por rangos de coste y mostrarlos en un diagrama de dispersión
        public static List<PuntoIntXY> ActivosCosteInformeXY(int IdInforme)
        {
            List<int> Rangos = new List<int>();
            List<PuntoIntXY> LActivosCosteXY = new List<PuntoIntXY>();
            Rangos.Add(1000);
            Rangos.Add(2000);
            Rangos.Add(5000);
            Rangos.Add(10000);
            Rangos.Add(20000);
            Rangos.Add(50000);
            Rangos.Add(100000);
            Rangos.Add(500000);
            Rangos.Add(1000000);
            Rangos.Add(1000000);
            List<int> ActivosPorCoste = ActivosInformeFactory.ActivosInformePorCoste(IdInforme, Rangos);
            //Se formatea los rangos para mostrarlo en el eje X del diagrama de barras
            List<String> ValoresRangos = ActivosEmpresaFactory.RecogeRangos(Rangos);
            for (int i = 0; i < ActivosPorCoste.Count(); i++)
            {
                PuntoIntXY NuevoPunto = new PuntoIntXY();
                NuevoPunto.X = ValoresRangos[i];
                NuevoPunto.Y = ActivosPorCoste[i];
                NuevoPunto.Serie = ValoresRangos[i];
                LActivosCosteXY.Add(NuevoPunto);
            }
            return LActivosCosteXY;
        }

        //Método que muestra la evolución de los activos según una lista de informes y los formatea para mostrarlos en una tabla
        public static List<PuntoIntXY> ActivosPorInformesXY(List<int> LInformes)
        {
            List<PuntoIntXY> LPuntos = new List<PuntoIntXY>();
            //Por cada informe de la lista
            foreach (int IdInforme in LInformes)
            {
                //Se recogen los activos de cada informe según su valor estratégico y se formatean para mostrarlos en la tabla
                int NumeroActivosInf = ActivosInformeFactory.NumeroTotalesActivosEmpresaInforme(IdInforme);
                PuntoIntXY numActPunto = new PuntoIntXY(IdInforme.ToString(), NumeroActivosInf, "Total");
                LPuntos.Add(numActPunto);
                int NumActAltoInf = ActivosInformeFactory.NumActivosInformeValor(IdInforme, 3);
                PuntoIntXY numActAltoPunto = new PuntoIntXY(IdInforme.ToString(), NumActAltoInf, "Alto");
                LPuntos.Add(numActAltoPunto);
                int NumActMedioInf = ActivosInformeFactory.NumActivosInformeValor(IdInforme, 2);
                PuntoIntXY numActMedioPunto = new PuntoIntXY(IdInforme.ToString(), NumActMedioInf, "Medio");
                LPuntos.Add(numActMedioPunto);
                int NumActBajoInf = ActivosInformeFactory.NumActivosInformeValor(IdInforme, 1);
                PuntoIntXY numActBajoPunto = new PuntoIntXY(IdInforme.ToString(), NumActBajoInf, "Bajo");
                LPuntos.Add(numActBajoPunto);
            }
            return LPuntos;
        }

        //Método que recoge los activos del Informe Base y los formatea para mostrarlos en una tabla del informe
        public static List<ActivosEvolucionInforme> ActivosInformeBase(int IdInforme)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            List<ActivosEvolucionInforme> ActivosEmpresa = (from ActInf in agenteBD.ActivosInformeEstablecer
                                                            join ActEmp in agenteBD.ActivosEmpresaEstablecer on ActInf.IdActivo equals ActEmp.IdActivo
                                                            join TipAct in agenteBD.TiposActivosEstablecer on ActEmp.IdTipoActivo equals TipAct.IdTipoActivo
                                                            where ActInf.IdInforme == IdInforme
                                                            orderby ActInf.ValorEstrategicoInforme descending, ActInf.CosteActivoInforme descending
                                                            select new ActivosEvolucionInforme { IdInforme = ActInf.IdInforme, Id = ActInf.IdActivo, Nombre = ActEmp.Nombre, TipoActivo = TipAct.TipoActivo, Coste = ActInf.CosteActivoInforme, ValorEstrategico = "Nulo" }).ToList();
            foreach (ActivosEvolucionInforme Act in ActivosEmpresa)
            {
                int IdValorEstrategico = (from ActInf in agenteBD.ActivosInformeEstablecer
                                          where ActInf.IdInforme == IdInforme && ActInf.IdActivo == Act.Id
                                          select ActInf.ValorEstrategicoInforme).Single();
                Act.ValorEstrategico = DeserializaValorEstrategico(IdValorEstrategico);
            }
            return ActivosEmpresa;
        }

        //Devuelve los activos que se han eliminado en una lista de informes, a partir
        //de un informe base formateados para mostrarlos en un informe
        public static List<ActivosEvolucionInforme> ActivosEvolucionEliminados(List<int> LInformes)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            LInformes.Sort();
            List<ActivosEvolucionInforme> LActivosDatInfElim = new List<ActivosEvolucionInforme>();
            //Recogemos los Activos del Informe Base
            for (int i = 0; i < LInformes.Count(); i++)
            {
                int IdInformeBase = LInformes[i];
                List<ActivosInforme> LActivosEliminados = new List<ActivosInforme>();
                IQueryable<int> ActivosInformeBase = from ActInf in agenteBD.ActivosInformeEstablecer
                                                     where ActInf.IdInforme == IdInformeBase
                                                     select ActInf.IdActivo;
                //Pasamos por cada Activo viendo sus activos y comparándolos con los de ActivosInformeBase
                for (int j = (i + 1); j < (LInformes.Count); j++)
                {
                    int IdInformeActual = LInformes[j];
                    IQueryable<int> ActivosInformeActual = from ActInf in agenteBD.ActivosInformeEstablecer
                                                           where ActInf.IdInforme == IdInformeActual
                                                           select ActInf.IdActivo;
                    //Sacamos los activos Eliminados del informe base al Informe Actual
                    IQueryable<int> ActivosEliminadosQuery = ActivosInformeBase.Except(ActivosInformeActual);
                    //Recorremos los activos eliminados y los añadimos a la lista si no habían sido añadidos anteriormente
                    foreach (int IdAct in ActivosEliminadosQuery)
                    {
                        ActivosInforme Act = (from ActInf in agenteBD.ActivosInformeEstablecer
                                              where ActInf.IdActivo == IdAct && ActInf.IdInforme == IdInformeBase
                                              select ActInf).Single();
                        bool nuevoActivo = true;
                        for (int k = 0; k < LActivosDatInfElim.Count(); k++)
                        {
                            if (LActivosDatInfElim[k].Id == Act.IdActivo)
                            {
                                nuevoActivo = false;
                            }
                        }
                        if (nuevoActivo)
                        {
                            ActivosEvolucionInforme ActivoEliminado = new ActivosEvolucionInforme();
                            ActivoEliminado.Id = Act.IdActivo;
                            ActivoEliminado.IdInformeBase = IdInformeBase;
                            ActivoEliminado.IdInforme = IdInformeActual;
                            ActivoEliminado.Nombre = ActivosInformeFactory.NombreActivoInforme(Act.IdActivo);
                            ActivoEliminado.TipoActivo = ActivosInformeFactory.TipoActivoActivoInforme(Act.IdActivo);
                            ActivoEliminado.Coste = Act.CosteActivoInforme;
                            String ValorEstrategico = ActivosEmpresaFactory.RecogeValorEstrategico(Act.ValorEstrategicoInforme);
                            ActivoEliminado.ValorEstrategico = ValorEstrategico;
                            LActivosDatInfElim.Add(ActivoEliminado);
                        }
                    }
                }
            }
            return LActivosDatInfElim;
        }

        //Devuelve para formatear en una tabla los activos que se han ido añadiendo según una lista de informes, a partir de un informe base
        public static List<ActivosEvolucionInforme> ActivosEvolucionNuevos(List<int> LInformes)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            LInformes.Sort();
            List<ActivosEvolucionInforme> LActivosDatInfNuevos = new List<ActivosEvolucionInforme>();
            //Recogemos los Activos del Informe Base
            for (int i = 0; i < LInformes.Count(); i++)
            {
                int IdInformeBase = LInformes[i];
                List<ActivosInforme> LActivosEliminados = new List<ActivosInforme>();
                IQueryable<int> ActivosInformeBase = from ActInf in agenteBD.ActivosInformeEstablecer
                                                     where ActInf.IdInforme == IdInformeBase
                                                     select ActInf.IdActivo;
                //Pasamos por cada Activo viendo sus activos y comparándolos con los ActivosBase
                for (int j = (i + 1); j < (LInformes.Count); j++)
                {
                    int IdInformeActual = LInformes[j];
                    IQueryable<int> ActivosInformeActual = from ActInf in agenteBD.ActivosInformeEstablecer
                                                           where ActInf.IdInforme == IdInformeActual
                                                           select ActInf.IdActivo;
                    //Sacamos los activos añadidos del informe base al Informe Actual
                    IQueryable<int> ActivosNuevosQuery = ActivosInformeActual.Except(ActivosInformeBase);
                    //Recorremos los activos nuevos y los añadimos a la lista si no habían sido añadidos anteriormente
                    foreach (int IdAct in ActivosNuevosQuery)
                    {
                        ActivosInforme Act = (from ActInf in agenteBD.ActivosInformeEstablecer
                                              where ActInf.IdActivo == IdAct && ActInf.IdInforme == IdInformeActual
                                              select ActInf).Single();
                        bool nuevoActivo = true;
                        for (int k = 0; k < LActivosDatInfNuevos.Count(); k++)
                        {
                            if (LActivosDatInfNuevos[k].Id == Act.IdActivo)
                            {
                                nuevoActivo = false;
                            }
                        }
                        //Si se ha encontrado un activo nuevo que no estaba en los informes anteriores, se añade a la lista
                        if (nuevoActivo)
                        {
                            ActivosEvolucionInforme ActivoNuevo = new ActivosEvolucionInforme();
                            ActivoNuevo.Id = Act.IdActivo;
                            ActivoNuevo.IdInformeBase = IdInformeBase;
                            ActivoNuevo.IdInforme = IdInformeActual;
                            ActivoNuevo.Nombre = ActivosInformeFactory.NombreActivoInforme(Act.IdActivo);
                            ActivoNuevo.TipoActivo = ActivosInformeFactory.TipoActivoActivoInforme(Act.IdActivo);
                            ActivoNuevo.Coste = Act.CosteActivoInforme;
                            String ValorEstrategico = ActivosEmpresaFactory.RecogeValorEstrategico(Act.ValorEstrategicoInforme);
                            ActivoNuevo.ValorEstrategico = ValorEstrategico;
                            LActivosDatInfNuevos.Add(ActivoNuevo);
                        }
                    }
                }
            }
            return LActivosDatInfNuevos;
        }
    }
}
